#ifndef __NET_CONNECTION__
#define __NET_CONNECTION__

#include<iostream>
#include<any>
#include<memory>
#include<functional>

#include<assert.h>

#include"../memory/buffer.hpp"
#include"socket.hpp"
#include"channel.hpp"
#include"eventloop.hpp"

class Connection;
using ConnectionPtr=std::shared_ptr<Connection>;

//enable_shared_from_this允许一个对象（通常由shared_ptr管理）生成一个指向自身的shared_ptr，
//即使对象自身是通过裸指针传递给shared_ptr构造函数的
//通信连接管理类
class Connection : public std::enable_shared_from_this<Connection>
{
public:
    typedef enum
    {
        DISCONNECTED,   //连接关闭
        CONNECTING,     //连接创建成功，待处理
        CONNECTED,      //连接创建成功，设置完成，可以通信
        DISCONNECTING   //连接待关闭
    }ConnectStatu;

    using ConnectionCallback=std::function<void(const ConnectionPtr&)>;
    using MessageCallback=std::function<void(const ConnectionPtr&,InBuffer*)>;
    using CloseCallback=std::function<void(const ConnectionPtr&)>;
    using EveryCallback=std::function<void(const ConnectionPtr&)>;

public:
    Connection(int conn_id,int sockfd,Eventloop* loop)
        :_connect_id(conn_id),_connect_sockfd(sockfd),_connect_loop(loop),
         _connect_channel(loop,sockfd),_connect_socket(sockfd)
    {
        _connect_channel.set_callback(std::bind(&Connection::handle_read,this),Channel::Read);
        _connect_channel.set_callback(std::bind(&Connection::handle_write,this),Channel::Write);
        _connect_channel.set_callback(std::bind(&Connection::handle_write,this),Channel::Error);
        _connect_channel.set_callback(std::bind(&Connection::handle_write,this),Channel::Close);
        _connect_channel.set_callback(std::bind(&Connection::handle_write,this),Channel::Every);
    }

    int get_sockfd(){return _connect_sockfd;}

    int get_connid(){return _connect_id;}

    std::any* get_context(){return &_connect_context;}

    void set_context(const std::any& context){_connect_context=context;}

    bool is_connected_statu(){return (_connect_statu==CONNECTED);}

    int get_timer_id(){return _connect_timer_id;}

    void set_timer_id(int id){_connect_timer_id=id;}

    const char* get_socket_addr(){return _connect_socket._socket_addr;}

    void set_connect_connect_cb(const ConnectionCallback& cb){_connect_connect_cb=cb;}

    void set_connect_message_cb(const MessageCallback& cb){_connect_message_cb=cb;}

    void set_connect_close_cb(const CloseCallback& cb){_connect_close_cb=cb;}

    void set_connect_every_cb(const EveryCallback& cb){_connect_every_cb=cb;}

    void set_connect_server_close_cb(const CloseCallback& cb){_connect_server_close_cb=cb;}

    void established(){_connect_loop->add_task(std::bind(&Connection::established_in_loop,this));}

    void send(const char* data,int len)
    {
        _connect_loop->add_task(std::bind(&Connection::send_in_loop,this,data,len));
    }

    void shutdown(){_connect_loop->add_task(std::bind(&Connection::shutdown_in_loop,this));}

    void release(){_connect_loop->add_task(std::bind(&Connection::release_in_loop,this));}

    void upgrade(const std::any& context,
                 const ConnectionCallback& conn,
                 const MessageCallback& msg,
                 const CloseCallback& close,
                 const EveryCallback& eve)
    {
        assert(_connect_loop->is_in_loop());
        _connect_loop->add_task(std::bind(&Connection::upgrade_in_loop,this,context,conn,msg,close,eve));
    }

    ~Connection()
    {
        DBG("release connection:%d",_connect_id);
    }

private:
    //channel的读回调函数
    void handle_read()
    {
        //向socket中读取内容到输入缓冲区
        int ret=_connect_inbuff.read_from_fd(_connect_sockfd);
        if(ret<0)
        {
            ERR("read data from socket error");
            this->shutdown_in_loop();
            return;
        }
        else if(ret==0)
        {
            INF("connection closed by peer");
            this->shutdown_in_loop();
            return;
        }
        _connect_message_cb(shared_from_this(),&_connect_inbuff);
    }

    //channel的写回调函数
    void handle_write()
    {
        while(_connect_outbuff.length())
        {
            int ret=_connect_outbuff.write_to_fd(_connect_sockfd);
            if(ret==-1)
            {
                ERR("write_to_fd error, close connect!");
                this->handle_close();
                return;
            }
            else if(ret==0)break;
        }

        if(_connect_outbuff.length()==0)
        {
            _connect_channel.set_events(Channel::Disable_Write);
            if(_connect_statu==DISCONNECTING)return release();
        }
    }

    //channel的错误回调函数
    void handle_error()
    {
        handle_close();
    }

    //channel的关闭回调函数
    void handle_close()
    {
        if(_connect_inbuff.length()>0&&_connect_message_cb)
            _connect_message_cb(shared_from_this(),&_connect_inbuff);
        release();
    }

    //channel的任意事件回调函数
    void handle_every()
    {
        if(_connect_every_cb)_connect_every_cb(shared_from_this());
    }

    //连接获取后，设置连接状态，启动读监听，调用回调函数
    void established_in_loop()
    {
        assert(_connect_statu==CONNECTING);
        _connect_statu=CONNECTED;

        _connect_channel.set_events(Channel::Be_Read);

        if(_connect_connect_cb)_connect_connect_cb(shared_from_this());
    }

    //将数据写入发送缓冲区，启动写监听
    void send_in_loop(const char* data,int len)
    {
        if(_connect_statu==DISCONNECTED)return;

        _connect_outbuff.write_to_buff(data,len);

        if(_connect_channel.set_events(Channel::Able_Write)==false)
            _connect_channel.set_events(Channel::Be_Write);
    }

    //释放connection前，检查读写缓冲区是否存在数据
    void shutdown_in_loop()
    {
        _connect_statu=DISCONNECTING;
        if(_connect_inbuff.length()>0&&_connect_message_cb)
            _connect_message_cb(shared_from_this(),&_connect_inbuff);

        if(_connect_outbuff.length()>0&&_connect_channel.set_events(Channel::Able_Write)==false)
            _connect_channel.set_events(Channel::Be_Write);

        if(_connect_outbuff.length()==0)release();
    }

    //从loop中释放connection接口
    void release_in_loop()
    {
        //修改连接状态
        _connect_statu=DISCONNECTED;
        //移除连接的事件监听
        _connect_channel.remove_channel();
        //关闭sockfd
        _connect_socket.Close();
        //执行关闭回调函数
        if(_connect_close_cb)_connect_close_cb(shared_from_this());
        //执行移除服务器内部管理的连接信息
        if(_connect_server_close_cb)_connect_server_close_cb(shared_from_this());
    }

    //切换应用层协议，重置上下文和回调处理函数
    //在eventloop中必须立刻执行，否则可能会出现新事件触发，协议还未切换
    void upgrade_in_loop(const std::any& context,
                         const ConnectionCallback& conn,
                         const MessageCallback& msg,
                         const CloseCallback& close,
                         const EveryCallback& eve)
    {
        _connect_context=context;
        _connect_connect_cb=conn;
        _connect_message_cb=msg;
        _connect_close_cb=close;
        _connect_every_cb=eve;
    }

private:
    uint64_t _connect_id;                   //connection的id
    int _connect_sockfd;                    //连接对应的socketfd
    int _connect_timer_id{-1};              //连接对应的timerid
    // bool _connect_is_release{false};        //
    ConnectStatu _connect_statu{CONNECTING};//连接状态

    InBuffer _connect_inbuff;               //输入缓冲区，存放读取到的数据
    OutBuffer _connect_outbuff;             //输出缓冲区，存放要发送的数据

    Socket _connect_socket;                 //socket的操作管理
    Channel _connect_channel;               //事件的操作管理
    Eventloop* _connect_loop;               //connection关联的eventloop

    std::any _connect_context;              //请求的接收处理上下文

    //connection的回调函数，由服务器模块设置
    ConnectionCallback _connect_connect_cb;
    MessageCallback _connect_message_cb;
    CloseCallback _connect_close_cb;
    EveryCallback _connect_every_cb;

    //connection从loop中移除的回调函数
    CloseCallback _connect_server_close_cb;
};

#endif